TreeviewCopyright © aleen42 all right reserved, powered by aleen42

先上一个例子,显示一个特别长的字符串:

      body: Row(
        children: <Widget>[
          Text(
            "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
            style: TextStyle(backgroundColor: Colors.cyan),
          ),
        ],
      ),

显示效果如下:

可以看到在最右边显示出错了,这是因为你要显示的内容超出了可显示的范围,Row 和 Column 都会出现这样的问题,当长度超出时,不会自动折行,在 Flutter 中,提供了 WrapFlow 来支持这种情况,称之为 “流式布局”。

Wrap

把上面例子中的 Row 改为 Wrap 之后看效果:

可以看到自动折行了,看一下属性:

  Wrap({
    Key key,
    this.direction = Axis.horizontal,    //子元素是垂直分布还是水平分布
    this.alignment = WrapAlignment.start,    //主轴方向上的对齐方式,默认为 start。
    this.spacing = 0.0,    //主轴方向上的间距。
    this.runAlignment = WrapAlignment.start,    //主轴方向相对的轴的对齐方式
    this.runSpacing = 0.0,    //主轴方向相对的轴的间距
    this.crossAxisAlignment = WrapCrossAlignment.start,
    this.textDirection,
    this.verticalDirection = VerticalDirection.down,
    List<Widget> children = const <Widget>[],
  })

属性这里注释都写的很清楚了,这里就不多做解释了。

Flow

以下内容转载自 简书 - Q吹个大气球Q - Flutter 布局(九)- Flow、Table、Wrap详解

Flow官方介绍是一个对 child 尺寸以及位置调整非常高效的控件,主要是得益于其 FlowDelegate。另外 Flow 在用转换矩阵 transformation matrices 对 child 进行位置调整的时候进行了优化。

Flow 以及其 child 的一些约束都会受到 FlowDelegate 的控制,例如重写 FlowDelegate 中的 geiSize,可以设置 Flow 的尺寸,重写其 getConstraintsForChild 方法,可以设置每个 child 的布局约束条件。

Flow 之所以高效,是因为其在定位过后,如果使用 FlowDelegate 中的 paintChildren 改变 child 的尺寸或者位置,只是重绘,并没有实际调整其位置。

例如:

const width = 80.0;
const height = 60.0;

class _MyStatefulWidgetState extends State<MyStatefulWidget> {
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(""),
      ),
      body: Flow(
        delegate: TestFlowDelegate(margin: EdgeInsets.fromLTRB(10.0, 10.0, 10.0, 10.0)),
        children: <Widget>[
          new Container(width: width, height: height, color: Colors.yellow,),
          new Container(width: width, height: height, color: Colors.green,),
          new Container(width: width, height: height, color: Colors.red,),
          new Container(width: width, height: height, color: Colors.black,),
          new Container(width: width, height: height, color: Colors.blue,),
          new Container(width: width, height: height, color: Colors.lightGreenAccent,),
        ],
      ),
    );
  }
}


class TestFlowDelegate extends FlowDelegate {
  EdgeInsets margin = EdgeInsets.zero;

  TestFlowDelegate({this.margin});
  @override
  void paintChildren(FlowPaintingContext context) {
    var x = margin.left;
    var y = margin.top;
    for (int i = 0; i < context.childCount; i++) {
      var w = context.getChildSize(i).width + x + margin.right;
      if (w < context.size.width) {
        context.paintChild(i,
            transform: new Matrix4.translationValues(
                x, y, 0.0));
        x = w + margin.left;
      } else {
        x = margin.left;
        y += context.getChildSize(i).height + margin.top + margin.bottom;
        context.paintChild(i,
            transform: new Matrix4.translationValues(
                x, y, 0.0));
        x += context.getChildSize(i).width + margin.left + margin.right;
      }
    }
  }

  @override
  bool shouldRepaint(FlowDelegate oldDelegate) {
    return oldDelegate != this;
  }
}

样例其实并不复杂,FlowDelegate 需要自己实现 child 的绘制,其实大多数时候就是位置的摆放。上面例子中,对每个 child 按照给定的 margin 值,进行排列,如果超出一行,则在下一行进行布局。

另外,对这个例子多做一个说明,对于上述 child 宽度的变化,这个例子是没问题的,如果每个 child 的高度不同,则需要对代码进行调整,具体的调整是换行的时候,需要根据上一行的最大高度来确定下一行的起始y坐标。

results matching ""

    No results matching ""